import time
import schedule
import logging
import json
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
import threading

# 添加当前目录到系统路径
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
sys.path.append(current_dir)

# 现在使用简单导入
from data_collector.stock_data import StockDataCollector
from data_collector.news_data import NewsDataCollector
from ai_analysis.model_connector import AIModelConnector
from strategy.strategy_generator import StrategyGenerator
from notification.notification_service import NotificationService
from storage.database import DatabaseManager
from user.user_manager import UserManager
from quantitative.quant_factory import QuantAnalyzerFactory
from strategy.enhanced_strategy_generator import EnhancedStrategyGenerator
from web.app_web import start_web_server

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("app.log"),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

class StockAnalysisApp:
    def __init__(self, config_path):
        # 加载配置
        with open(config_path, 'r', encoding='utf-8') as f:
            self.config = json.load(f)
            
        # 初始化各模块
        self.stock_data_collector = StockDataCollector(
            self.config['tushare']['api_token'], 
            self.config['data_collection']
        )
        
        self.news_collector = NewsDataCollector(self.config['data_collection'])
        self.ai_connector = AIModelConnector(self.config['ai_models'])
        
        # 初始化量化工厂
        self.quant_factory = QuantAnalyzerFactory(self.config)
        
        # 使用增强版策略生成器
        self.strategy_generator = EnhancedStrategyGenerator(self.config['strategies'])
        
        self.notification_service = NotificationService(self.config['notification'])
        self.db_manager = DatabaseManager(self.config['database'])
        
        # 为UserManager创建一个符合其期望的配置对象
        user_config = {
            'mongodb_uri': self.config['database']['mongodb']['connection_string'],
            'database': self.config['database']['mongodb']['database'],
            'db_collection': self.config['users']['db_collection']
        }
        self.user_manager = UserManager(user_config)
        
        # 线程池
        self.executor = ThreadPoolExecutor(max_workers=self.config['system']['max_workers'])
        
        # 在初始化后添加测试代码
        try:
            # 测试数据库连接
            self.db_manager.db.list_collection_names()
            logger.info("数据库连接成功")
        except Exception as e:
            logger.error(f"数据库连接失败: {str(e)}")
            logger.warning("系统将继续运行，但数据将无法保存")
        
    def analyze_stock(self, stock_code, analyzer_type=None):
        """分析单个股票并生成策略，可选择使用的量化框架"""
        start_time = datetime.now()
        
        try:
            logger.info(f"开始分析股票: {stock_code}, 使用框架: {analyzer_type or '默认'}")
            
            # 启用量化分析（如果Hikyuu已成功安装）
            USE_QUANT = True
            
            # 1. 获取股票数据
            stock_data = self.stock_data_collector.get_stock_indicators(stock_code)
            
            # 2. 获取相关新闻
            news_data = self.news_collector.get_stock_announcements(stock_code)
            social_data = self.news_collector.get_social_sentiment(stock_code)
            
            # 3. AI分析
            tech_analysis = self.ai_connector.get_analysis_result(
                stock_code, stock_data, news_data, "technical"
            )
            
            fundamental_analysis = self.ai_connector.get_analysis_result(
                stock_code, stock_data, news_data, "fundamental"
            )
            
            summary = self.ai_connector.get_analysis_result(
                stock_code, stock_data, news_data, "summary"
            )
            
            # 4. 保存分析结果
            self.db_manager.save_analysis_result(stock_code, "technical", tech_analysis)
            self.db_manager.save_analysis_result(stock_code, "fundamental", fundamental_analysis)
            self.db_manager.save_analysis_result(stock_code, "summary", summary)
            
            # 5. 生成策略，可以指定使用的量化框架
            short_term = self.strategy_generator.generate_short_term_strategy(
                stock_code, tech_analysis, analyzer_type
            )
            
            medium_term = self.strategy_generator.generate_medium_term_strategy(
                stock_code, tech_analysis, fundamental_analysis, analyzer_type
            )
            
            long_term = self.strategy_generator.generate_long_term_strategy(
                stock_code, fundamental_analysis, analyzer_type
            )
            
            # 6. 保存策略
            self.db_manager.save_strategy(stock_code, "short", short_term)
            self.db_manager.save_strategy(stock_code, "medium", medium_term)
            self.db_manager.save_strategy(stock_code, "long", long_term)
            
            # 7. 获取股票名称
            stock_info = self.stock_data_collector.get_realtime_quotes([stock_code])
            stock_name = stock_info.iloc[0]['name'] if not stock_info.empty else stock_code
            
            # 8. 如果使用了量化框架，获取额外分析结果
            quant_analysis = None
            if USE_QUANT:
                try:
                    analyzer = self.quant_factory.get_analyzer(analyzer_type)
                    if analyzer_type == 'hikyuu':
                        quant_analysis = analyzer.analyze_stock(stock_code)
                    elif analyzer_type == 'qlib':
                        quant_analysis = analyzer.get_market_analysis(stock_code)
                except Exception as e:
                    logger.error(f"获取量化分析失败: {str(e)}")
            
            end_time = datetime.now()
            duration = (end_time - start_time).total_seconds()
            logger.info(f"分析股票 {stock_code} 完成，耗时: {duration:.2f}秒")
            
            # 记录性能指标
            self.db_manager.save_performance_metric({
                "operation": "analyze_stock",
                "stock_code": stock_code,
                "duration": duration,
                "timestamp": end_time,
                "analyzer_used": analyzer_type
            })
            
            return {
                "stock_code": stock_code,
                "stock_name": stock_name,
                "strategies": {
                    "short": short_term,
                    "medium": medium_term,
                    "long": long_term
                },
                "summary": summary,
                "quant_analysis": quant_analysis,
                "analyzer_used": analyzer_type
            }
            
        except Exception as e:
            logger.error(f"分析股票 {stock_code} 时发生错误: {str(e)}")
            return {
                "stock_code": stock_code,
                "error": str(e)
            }
            
    def notify_users(self, stock_analysis):
        """通知订阅该股票的用户"""
        if "error" in stock_analysis:
            logger.error(f"不发送通知，因为股票 {stock_analysis['stock_code']} 分析出错")
            return
            
        stock_code = stock_analysis["stock_code"]
        stock_name = stock_analysis["stock_name"]
        
        # 获取订阅该股票的用户
        subscribers = self.user_manager.get_stock_subscribers(stock_code)
        
        for user in subscribers:
            # 根据用户偏好确定发送哪些策略
            strategy_types = user.get('strategy_preference', ['short'])
            
            for strategy_type in strategy_types:
                strategy = stock_analysis['strategies'][strategy_type]
                
                # 如果策略建议不是观望且置信度不低，才发送通知
                if strategy['action'] != 'hold' or strategy['confidence'] != 'low':
                    message = self.notification_service.format_strategy_message(
                        stock_code, stock_name, strategy
                    )
                    
                    # 根据用户偏好发送通知
                    if 'sms' in user.get('notification_methods', []):
                        status = self.notification_service.send_sms(user['phone'], message)
                        self.db_manager.save_notification(user['id'], 'sms', message, status)
                        
                    if 'wechat' in user.get('notification_methods', []):
                        status = self.notification_service.send_wechat(user['wechat_id'], message)
                        self.db_manager.save_notification(user['id'], 'wechat', message, status)
                        
                    if 'email' in user.get('notification_methods', []):
                        subject = f"{stock_name}({stock_code}) {strategy_type}策略提醒"
                        status = self.notification_service.send_email(user['email'], subject, message)
                        self.db_manager.save_notification(user['id'], 'email', message, status)
    
    def run_daily_analysis(self):
        """执行每日分析"""
        try:
            logger.info("开始每日分析任务")
            stock_list = self.config['monitoring']['stock_list']
            
            for stock_code in stock_list:
                try:
                    self.analyze_stock(stock_code)
                except Exception as e:
                    logger.error(f"分析股票 {stock_code} 失败: {str(e)}")
                    # 继续分析下一只股票，不中断整个流程
            
            logger.info("每日分析任务完成")
        except Exception as e:
            logger.critical(f"每日分析任务异常: {str(e)}")
            # 尝试恢复核心服务
            self._recover_core_services()
        
    def _recover_core_services(self):
        """尝试恢复核心服务"""
        logger.info("尝试恢复核心服务...")
        try:
            # 重新初始化数据库连接
            self.db_manager = DatabaseManager(self.config['database'])
            logger.info("数据库连接已恢复")
        except Exception as e:
            logger.error(f"恢复数据库连接失败: {str(e)}")
    
    def start(self):
        """启动应用程序"""
        logger.info("股票实时AI分析系统启动")
        
        # 设置定时任务
        # 每个交易日收盘后运行分析
        schedule.every().monday.at("15:30").do(self.run_daily_analysis)
        schedule.every().tuesday.at("15:30").do(self.run_daily_analysis)
        schedule.every().wednesday.at("15:30").do(self.run_daily_analysis)
        schedule.every().thursday.at("15:30").do(self.run_daily_analysis)
        schedule.every().friday.at("15:30").do(self.run_daily_analysis)
        
        # 主循环
        while True:
            schedule.run_pending()
            time.sleep(1)

    def check_health(self):
        """检查系统健康状态"""
        health = {
            "status": "healthy",
            "components": {
                "database": "unknown",
                "data_collector": "unknown",
                "ai_model": "unknown"
            },
            "last_check": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        
        # 检查数据库连接
        try:
            self.db_manager.db.list_collection_names()
            health["components"]["database"] = "healthy"
        except:
            health["components"]["database"] = "unhealthy"
            health["status"] = "degraded"
        
        # 检查数据收集器
        try:
            self.stock_data_collector.get_realtime_quotes(["000001.SZ"])
            health["components"]["data_collector"] = "healthy"
        except:
            health["components"]["data_collector"] = "unhealthy"
            health["status"] = "degraded"
        
        # 检查AI模型连接
        try:
            test_result = self.ai_connector.test_connection()
            health["components"]["ai_model"] = "healthy" if test_result else "degraded"
        except:
            health["components"]["ai_model"] = "unhealthy"
            health["status"] = "degraded"
        
        return health

    def start_web_server(self, port=5000):
        """启动Web服务器"""
        web_thread = threading.Thread(target=start_web_server, args=(self, port))
        web_thread.daemon = True
        web_thread.start()
        logger.info(f"Web服务器已启动，端口：{port}")

if __name__ == "__main__":
    app = StockAnalysisApp("config.json")
    
    # 启动Web服务器
    app.start_web_server(port=5000)
    
    # 测试分析单只股票
    test_stock = "000001.SZ"  # 平安银行
    print(f"\n开始测试分析股票: {test_stock}")
    result = app.analyze_stock(test_stock)
    print(f"分析结果摘要: {result.get('summary', '无摘要')}")
    print(f"短期策略: {result.get('strategies', {}).get('short', {}).get('action', '无建议')}")
    
    print("\n系统已启动，Web界面可通过 http://localhost:5000 访问")
    
    # 继续运行常规系统
    app.start() 